package com.yupi.yupao.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yupi.yupao.model.domain.User;
import com.yupi.yupao.service.AsyncCacheService;
import com.yupi.yupao.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;

/**
 * 异步缓存预热服务实现
 */
@Service
@Slf4j
public class AsyncCacheServiceImpl implements AsyncCacheService {

    @Resource
    private UserService userService;

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    /**
     * 缓存过期时间（毫秒）
     */
    private static final long CACHE_EXPIRATION_MS = 2 * 60 * 60 * 1000L; // 2小时

    /**
     * 用户登录后异步预热推荐用户缓存
     * 使用@Async注解标记此方法在单独的线程中执行，不影响主请求流程
     * 
     * @param user 登录用户
     */
    @Async("asyncTaskExecutor")
    @Override
    public void asyncPreheatUserRecommend(User user) {
        long startTime = System.currentTimeMillis();
        
        try {
            // 检查是否已经有缓存
            String redisKey = String.format("yupao:user:recommend:%s", user.getId());
            ValueOperations<String, Object> valueOperations = redisTemplate.opsForValue();
            
            // 如果缓存已存在，不再预热
            if (Boolean.TRUE.equals(redisTemplate.hasKey(redisKey))) {
                log.info("用户 {} 的推荐缓存已存在，跳过预热", user.getId());
                return;
            }
            
            log.info("开始为用户 {} 异步预热推荐列表缓存", user.getId());
            
            // 查询推荐用户列表
            QueryWrapper<User> queryWrapper = new QueryWrapper<>();
            // 一次缓存更多数据，提高缓存命中率
            Page<User> userPage = userService.page(new Page<>(1, 50), queryWrapper);
            
            // 写入缓存
            valueOperations.set(redisKey, userPage, CACHE_EXPIRATION_MS, TimeUnit.MILLISECONDS);
            
            long endTime = System.currentTimeMillis();
            log.info("用户 {} 推荐列表异步预热完成，耗时: {}ms", user.getId(), (endTime - startTime));
        } catch (Exception e) {
            log.error("用户 {} 推荐列表异步预热失败", user.getId(), e);
        }
    }
} 